home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / shell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  4.6 KB  |  219 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #ifdef CONFIG_H
  4. #   include "config.h"
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <sys/wait.h>
  9. #include <limits.h>
  10. #include <signal.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <unistd.h>
  15.  
  16. #define SHELL_C
  17. #define I_GETMSG_C
  18. #define I_PROMPT_C
  19. #define I_GETTK_C
  20. #define I_INIT_C
  21.  
  22. #include "origami.h"
  23. #include <h/envvar_str.h>
  24. #include <lib/ori_add_lib.h>
  25. /*}}}  */
  26.  
  27. /*{{{  variables*/
  28. public boolean force_sh=False;
  29. public boolean secure=
  30. #ifdef SECURE
  31.                    True;
  32. #else
  33.                    False;
  34. #endif
  35. public char const *shell_name;
  36.  
  37. #define MAX_PIPES 4
  38. private int p_used=0;
  39. private struct ph { FILE *f;pid_t id; } pipe_handle[MAX_PIPES];
  40. /*}}}  */
  41.  
  42. /*{{{  get_shell*/
  43. private const char *get_shell(void)
  44.  { const char *active_shell;
  45.    static const char bourne_shell[]=BOURNE_SHELL;
  46.  
  47.    if (secure)
  48.       active_shell=shell_name;
  49.    else if (force_sh)
  50.       active_shell=bourne_shell;
  51.    else
  52.     { active_shell=getenv(SHELL);
  53.       if (!active_shell || !active_shell[0])
  54.          active_shell=bourne_shell;
  55.     }
  56.    if (active_shell && !active_shell[0])
  57.       active_shell=0;
  58.    return(active_shell);
  59.  }
  60. /*}}}  */
  61. /*{{{  close_pipe_f*/
  62. private void close_pipe_f(void)
  63.  {
  64.    while (p_used)
  65.       fclose(pipe_handle[--p_used].f);
  66.    if (rcfile)
  67.       fclose(rcfile);
  68.    if (msg_file>=0)
  69.       close(msg_file);
  70.  }
  71. /*}}}  */
  72. /*{{{  flush_all*/
  73. private void flush_all(void) { fflush(stdout);fflush(stderr); }
  74. /*}}}  */
  75. /*{{{  waitfor*/
  76. private int waitfor(pid_t pid)
  77. { int i;
  78.   pid_t j;
  79.  
  80.   while (pid!=(j=waitpid(pid,&i,0)) || WIFSTOPPED(i))
  81.      if (-1==j)
  82.         return(-1);
  83.   return(WIFEXITED(i) ? WEXITSTATUS(i) : -1);
  84. }
  85. /*}}}  */
  86.  
  87. /*{{{  subshell*/
  88. int subshell(const char * const cmd)
  89. {
  90.   pid_t child;
  91.   const char *active_shell;
  92.  
  93.   if (!(active_shell=get_shell()))
  94.      return(EX_NOPERM);
  95.   flush_all();
  96.   signal(SIGINT,SIG_IGN);
  97.   switch ((child=fork()))
  98.    { case 0:
  99.       /*{{{  child*/
  100.         signal(SIGINT,SIG_DFL);
  101.         close_pipe_f();
  102.         execl(active_shell,active_shell,cmd?"-c":(char*)0,cmd,(char*)0);
  103.         exit(127);
  104.       /*}}}  */
  105.      default:
  106.       /*{{{  wait for child*/
  107.       { int status;
  108.  
  109.         status=waitfor(child);
  110.         signal(SIGINT,ori_abort);
  111.         return status;
  112.       }
  113.       /*}}}  */
  114.      case -1:
  115.       /*{{{  fork failed*/
  116.         msg_message(M_FORKFAIL);
  117.         signal(SIGINT,ori_abort);
  118.         return(-1);
  119.       /*}}}  */
  120.    }
  121. }
  122. /*}}}  */
  123. /*{{{  open_shell*/
  124. public FILE *open_shell(const char * const prog,const char * const type)
  125.  {
  126.    /*{{{  variables*/
  127.    FILE *fout;
  128.    const char *active_shell;
  129.    int d[2];
  130.    boolean reading;
  131.    /*}}}  */
  132.  
  133.    fout=0;
  134.    if
  135.     (    p_used<MAX_PIPES
  136.       && (type && ((reading=(type[0]=='r')) || type[0]=='w') && type[1]=='\0')
  137.       && (active_shell=get_shell())
  138.       && !pipe(d)
  139.     )
  140.     { flush_all();
  141.       signal(SIGINT,SIG_IGN);
  142.       switch ((pipe_handle[p_used].id=fork()))
  143.        { case 0:
  144.           /*{{{  child*/
  145.             signal(SIGINT,SIG_DFL);
  146.             close_pipe_f();
  147.             if (reading)
  148.              /*{{{  stdout*/
  149.              { int to;
  150.  
  151.                to=fileno(stdout);
  152.                fclose(stdout);
  153.                dup2(d[1],to);
  154.                close(d[0]);
  155.              }
  156.              /*}}}  */
  157.             else
  158.              /*{{{  stdin*/
  159.              { int to;
  160.  
  161.                to=fileno(stdin);
  162.                fclose(stdin);
  163.                dup2(d[0],to);
  164.                close(d[1]);
  165.              }
  166.              /*}}}  */
  167.             execl(active_shell,active_shell,"-c",prog,(char*)0);
  168.             exit(127);
  169.           /*}}}  */
  170.          default:
  171.           /*{{{  setup filehandle*/
  172.             fout=pipe_handle[p_used].f=fdopen(d[reading?0:1],type);
  173.             if (fout)
  174.              { close(d[reading?1:0]);
  175.                p_used++;
  176.                break;
  177.              }
  178.             else
  179.                goto fork_fail_handling;
  180.           /*}}}  */
  181.          case -1:
  182.          fork_fail_handling:
  183.           /*{{{  error, fork failed*/
  184.             close(d[0]);
  185.             close(d[1]);
  186.             if (pipe_handle[p_used].id>=0)
  187.              { kill(pipe_handle[p_used].id,SIGTERM);
  188.                waitfor(pipe_handle[p_used].id);
  189.              }
  190.             msg_message(M_FORKFAIL);
  191.             signal(SIGINT,ori_abort);
  192.             break;
  193.           /*}}}  */
  194.        }
  195.     }
  196.    return(fout);
  197.  }
  198. /*}}}  */
  199. /*{{{  close_shell*/
  200. public int close_shell(FILE *f)
  201.  { struct ph *p;
  202.  
  203.    p=pipe_handle+MAX_PIPES;
  204.    do
  205.       if (f==(--p)->f)
  206.        { int r;
  207.  
  208.          fclose(p->f);
  209.          r=waitfor(p->id);
  210.          *p=pipe_handle[--p_used];
  211.          pipe_handle[p_used].f=0;
  212.          return(r);
  213.        }
  214.    while (p!=pipe_handle);
  215.  
  216.    return(-1);
  217.  }
  218. /*}}}  */
  219.